'use client'; import { useState, useEffect, useCallback } from 'react'; import { fetchApi } from '@/lib/utils/client'; import type { ActiveSessionResponse, SessionHistoryResponse, SessionHistoryItem } from '@/types/response/crew/session'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; type Props = { crewID: number }; export default function CrewSessionTab({ crewID }: Props) { const [activeSession, setActiveSession] = useState(null); const [history, setHistory] = useState([]); const [historyTotal, setHistoryTotal] = useState(0); const [loading, setLoading] = useState(true); const [sessionTitle, setSessionTitle] = useState(''); const [starting, setStarting] = useState(false); const [ending, setEnding] = useState(false); const fetchActiveSession = useCallback(async () => { try { const res = await fetchApi(`/api/studio/crew/session/active/${crewID}`); setActiveSession(res.data ?? null); } catch {} }, [crewID]); const fetchHistory = useCallback(async () => { try { const res = await fetchApi(`/api/studio/crew/session/history/${crewID}?page=1&perPage=10`); setHistory(res.data?.list ?? []); setHistoryTotal(res.data?.total ?? 0); } catch {} }, [crewID]); useEffect(() => { setLoading(true); Promise.all([fetchActiveSession(), fetchHistory()]).finally(() => setLoading(false)); }, [fetchActiveSession, fetchHistory]); const handleStart = async () => { if (!sessionTitle.trim()) { alert('방송 제목을 입력해 주세요.'); return; } setStarting(true); try { await fetchApi('/api/crew/session/start', { method: 'POST', body: { crewID, title: sessionTitle.trim() } }); setSessionTitle(''); fetchActiveSession(); } catch (err: unknown) { alert(err instanceof Error ? err.message : '세션 시작에 실패했습니다.'); } finally { setStarting(false); } }; const handleEnd = async () => { if (!activeSession) return; if (!confirm('크루 방송을 종료하시겠습니까?\n종료 시 크루원에게 정산 결과가 전송됩니다.')) return; setEnding(true); try { await fetchApi('/api/crew/session/end', { method: 'POST', body: { crewSessionID: activeSession.crewSessionID } }); setActiveSession(null); fetchHistory(); } catch (err: unknown) { alert(err instanceof Error ? err.message : '세션 종료에 실패했습니다.'); } finally { setEnding(false); } }; if (loading) return

준비 중...

; return ( <> {activeSession ? (
{activeSession.title} {activeSession.status === 'Inviting' ? '동의 대기 중' : '방송 중'}
{activeSession.totalAmount.toLocaleString()}원
총 후원액
{activeSession.totalDonationCount}건
후원 건수
{activeSession.consents.filter(c => c.isConsented).length}/{activeSession.consents.length}
동의 현황
크루원 동의 현황
{activeSession.consents.map(c => (
{c.isConsented ? '✓' : '⏳'}{c.nickname}
))}
{activeSession.status === 'Active' && activeSession.summaries.length > 0 && (
{activeSession.summaries.map(s => ( ))}
순위크루원후원액건수기여율
{s.rank}위{s.nickname}{s.totalAmount.toLocaleString()}원{s.donationCount}건{s.contributionRate.toFixed(1)}%
)}
) : (
새 크루 방송 시작
setSessionTitle(e.target.value)} onKeyDown={e => e.key === 'Enter' && handleStart()} />
)}
지난 방송 ({historyTotal}건)
{history.length === 0 ? ( ) : history.map(h => ( ))}
제목총 후원액건수시작종료
아직 진행한 크루 방송이 없습니다.
{h.title}{h.totalAmount.toLocaleString()}원{h.totalDonationCount}건{h.startedAt ? new Date(h.startedAt).toLocaleString('ko-KR') : '-'}{h.endedAt ? new Date(h.endedAt).toLocaleString('ko-KR') : '-'}
); }